﻿using MediatR;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Ordering.Domain.Abstracter;

namespace Order.Infrastructure.Interceptors
{
    /// <summary>
    /// 领域事件拦截器，用于在保存更改时，发布领域事件
    /// </summary>
    /// <param name="mediator"></param>
    public class DomainEventInterceptor(IMediator mediator) : SaveChangesInterceptor
    {
        public override  InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
        {
            var context = eventData.Context;
            // Do something before saving changes
            DispatchDomainEvents(context).GetAwaiter().GetResult();
            return base.SavingChanges(eventData, result);
        }



        public override async ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)
        {
            var context = eventData.Context;
           await DispatchDomainEvents(context);

            return await base.SavingChangesAsync(eventData, result, cancellationToken);
        }

        private async Task DispatchDomainEvents(DbContext context)
        {
            if (context == null) return;

            var aggregates = context.ChangeTracker
                .Entries<IAggregate>()
                .Where(a => a.Entity.DomainEvents.Any())
                .Select(a => a.Entity);

            var domainEvents = aggregates
                .SelectMany(a => a.DomainEvents)
                .ToList();

            aggregates.ToList().ForEach(a => a.ClearDomainEvents());

            foreach (var domainEvent in domainEvents)
                await mediator.Publish(domainEvent);


        }
    }
}
